package com.example.demo.service.jobhandler;

import com.example.demo.po.UMeidaProcess;
import com.example.demo.service.UMediaService;
import com.example.demo.service.UMeidaProcessService;
import com.example.demo.util.Mp4VideoUtil;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @Classname VideoTask
 * @Description TODO
 * @Date 2023/5/16 10:31
 * @Created by Zh_Cn
 */

@Component
@Slf4j
public class VideoTask {

    @Autowired
    UMediaService uMediaService;
    @Value("${videoprocess.ffmpegpath}")
    String ffmpegpath;

    @Autowired
    UMeidaProcessService uMeidaProcessService;

    @XxlJob("plantvideo")
    public void videoJobHandler() throws InterruptedException {
        //定义分片参数
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        //取出cpu核心数
        int processors = Runtime.getRuntime().availableProcessors();
        //一次处理视频数量不要超过cpu核心数
        List<UMeidaProcess> mediaProcesses = uMeidaProcessService.getMediaProcessList(shardIndex, shardTotal, processors);
        int size = mediaProcesses.size();
        log.debug("取出待处理视频任务{}条", size);
        if (size<=0){
            return;
        }
        //启动size个线程的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(size);
        //计数器
        CountDownLatch count = new CountDownLatch(size);
        //将处理任务加入线程池
        mediaProcesses.forEach(mediaProcess -> {
            executorService.execute(()->{
                try {
                    //获取任务id
                    Long id = mediaProcess.getId();
                    //抢占任务
                    boolean b = uMeidaProcessService.startTask(id);
                    if (b) {
                        log.debug("抢占任务失败,任务id:{}", id);
                        return;
                    }
                    log.debug("开始执行任务{}", mediaProcess);

                    //获取捅
                    String bucket = mediaProcess.getBucket();
                    //获取存储路径
                    String filePath = mediaProcess.getPath();
                    //获取md5
                    String fileId = mediaProcess.getFileid();
                    //获取文件名称
                    String filename = mediaProcess.getFilename();
                    //将要下载的文件下载到服务器上
                    File file = uMediaService.downloadFileFromMinIO(bucket, filePath);
                    if (file == null) {
                        log.debug("下载视频出错,任务id:{},bucket:{},objectName:{}", id, bucket, filePath);
                        //保存任务处理失败的结果
                        uMeidaProcessService.saveProcessFinishStatus(id, "3", fileId,
                                null, "下载视频到本地失败");
                        return;
                    }
                    //源avi视频的路径
                    String video_path = file.getAbsolutePath();
                    //转换后mp4文件的名称
                    String mp4_name = fileId + ".mp4";
                    //转换后mp4文件的路径
                    //先创建一个临时文件，作为转换后的文件
                    File mp4File = null;
                    try {
                        mp4File = File.createTempFile("minio", ".mp4");
                    } catch (IOException e) {
                        log.debug("创建临时文件异常,{}", e.getMessage());
                        //保存任务处理失败的结果
                        uMeidaProcessService.saveProcessFinishStatus(id, "3", fileId,
                                null, "创建临时文件异常");
                        return;
                    }
                    String mp4_path = mp4File.getAbsolutePath();
                    //创建工具类对象
                    Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegpath, video_path, mp4_name, mp4_path);
                    //开始视频转换，成功将返回success,失败返回失败原因
                    String result = videoUtil.generateMp4();
                    if (!result.equals("success")) {

                        log.debug("视频转码失败,原因:{},bucket:{},objectName:{},", result, bucket, filePath);
                        uMeidaProcessService.saveProcessFinishStatus(id, "3", fileId,
                                null, result);
                        return;

                    }
                    //上传到minio
                    boolean b1 = uMediaService.addUMediaToMinIO(mp4File.getAbsolutePath(),
                            "video/mp4", bucket, filePath);
                    if (!b1) {
                        log.debug("上传mp4到minio失败,taskid:{}", id);
                        uMeidaProcessService.saveProcessFinishStatus(id, "3", fileId,
                                null, "上传mp4到minio失败");
                        return;
                    }
                    //mp4文件的url
                    String url = getFilePath(fileId, ".mp4");

                    //更新任务状态为成功
                    uMeidaProcessService.saveProcessFinishStatus(id, "2", fileId, url,
                            "创建临时文件异常");
                }
                finally {
                    count.countDown();
                }
            });
        });
        count.await(30, TimeUnit.MINUTES);
    }
        private String getFilePath(String fileMd5,String fileExt){
            return   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/"
                    +fileMd5 +fileExt;
        }
    }
